﻿// 开发者:micropu
// 公司:佛山远钧智慧科技有限公司

using Admin.NET.Application.Service.Device.Dto;
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TouchSocket.Http.WebSockets;

namespace Admin.NET.Application;


/// <summary>
/// IClientWebSocketManager 接口实现
/// </summary>
public class ClientWebSocketManager : IClientWebSocketManager
{
    private readonly ConcurrentDictionary<string, IWebSocket> _connections = new();
    private readonly ConcurrentDictionary<string, TaskCompletionSource<string>> _responseWaiters = new(); // 等待响应的任务


    public void AddConnection(string deviceSn, IWebSocket webSocket)
    {
        //面这个判断是为了防止重复添加
        _connections.TryAdd(deviceSn, webSocket);
        // _connections[deviceSn] = webSocket;
    }

    public IWebSocket GetConnection(string deviceSn)
    {
        _connections.TryGetValue(deviceSn, out var webSocket);
        return webSocket;
    }

    public void ReceiveMessage(string deviceSn, string message)
    {
        if (_responseWaiters.TryGetValue(deviceSn, out var tcs))
        {
            tcs.SetResult(message);
            _responseWaiters.Remove(deviceSn, out tcs);
        }
    }

    public Task RemoveConnectionAsync(string deviceSn)
    {
        if (_connections.TryGetValue(deviceSn, out var webSocket))
        {
            _connections.Remove(deviceSn, out webSocket);
            webSocket.SafeClose();
            // await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closed by the server", CancellationToken.None);
        }

        return Task.CompletedTask;
    }

    public ConcurrentDictionary<string, IWebSocket> SelectAllConnections()
    {
        return _connections;
    }

    public async Task<CommonClientResult> SendAndWaitForResponseAsync(string deviceSn, string message, TimeSpan timeout)
    {
        if (_connections.TryGetValue(deviceSn, out var webSocket) && webSocket.Client.Online)
        {
            TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
            _responseWaiters[deviceSn] = tcs;

            var buffer = Encoding.UTF8.GetBytes(message);
            await webSocket.SendAsync(message);

            var task = await Task.WhenAny(tcs.Task, Task.Delay(timeout));
            if (task == tcs.Task)
            {
                var result = JsonConvert.DeserializeObject<CommonClientResult>(tcs.Task.Result);
                //return tcs.Task.Result;
                result.result = tcs.Task.Result;
                result.msg = result.code.GetDescription();
                return result;
            }
            else
            {
                return new CommonClientResult() { code = ResponseCode.ExpectedTime, msg = "未在预期时间内收到回复未在预期时间内收到回复。" };

                //未在预期时间内收到回复未在预期时间内收到回复
                //throw new TimeoutException("Response not received in the expected time.");
            }
        }
        else
        {
            return new CommonClientResult() { code = ResponseCode.AvailableOrClosed, msg = "连接不可用或已关闭连接不可用或已关闭。" };
           //连接不可用或已关闭连接不可用或已关闭
           // throw new InvalidOperationException("Connection not available or closed.");
        }
    }

    public async Task SendAsync(string deviceSn, string message)
    {
        if (_connections.TryGetValue(deviceSn, out var webSocket))
        {
            // var buffer = Encoding.UTF8.GetBytes(message);
            // await webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None);
            await webSocket.SendAsync(message);
        }
    }
}
